﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TetrisService
{
    /// <summary>
    /// This class represents an T tetromino. The notation is being reference as on the wikipedia.
    /// </summary>
    public class TetrominoT : Tetromino
    {
        private static readonly int COLOR = 6;
        private static readonly int COLOR_IN_ACTION = (-1) * COLOR;

        private int currentPosition = 0;

        /// <summary>
        /// Initializes a new instance of the <see cref="TetrominoT"/> class.
        /// </summary>
        /// <param name="board">The board.</param>
        public TetrominoT(int[][] board)
            : base(board)
        {
            tetromino[BLOCK_0] = new TetrominoBlock(4, -1);
            tetromino[BLOCK_1] = new TetrominoBlock(5, -1);
            tetromino[BLOCK_2] = new TetrominoBlock(6, -1);
            tetromino[BLOCK_3] = new TetrominoBlock(5, 0);
            fillCurrentTetromino(COLOR_IN_ACTION);
        }

        /// <summary>
        /// Rotates the tetromino to the vertical positioning.
        /// </summary>
        /// <param name="tmpPieces">The TMP pieces.</param>
        /// <returns></returns>
        private bool moveToPosition0(TetrominoBlock[] tmpPieces)
        {
            if (hasColisionInIncompleteBlock(tmpPieces[BLOCK_0].getX() - 1, tmpPieces[BLOCK_0].getY() - 1))
            {
                moveRight(tmpPieces);
            }
            tmpPieces[BLOCK_0].addX(-1);
            tmpPieces[BLOCK_0].addY(-1);

            tmpPieces[BLOCK_2].addX(1);
            tmpPieces[BLOCK_2].addY(1);

            tmpPieces[BLOCK_3].addX(-1);
            tmpPieces[BLOCK_3].addY(1);
            return true;
        }

        /// <summary>
        /// Rotates the tetromino to the horizontal positioning.
        /// </summary>
        /// <param name="tmpPieces">The TMP pieces.</param>
        /// <returns></returns>
        private bool moveToPosition1(TetrominoBlock[] tmpPieces)
        {
            tmpPieces[BLOCK_0].addX(1);
            tmpPieces[BLOCK_0].addY(-1);

            tmpPieces[BLOCK_2].addX(-1);
            tmpPieces[BLOCK_2].addY(1);

            tmpPieces[BLOCK_3].addX(-1);
            tmpPieces[BLOCK_3].addY(-1);
            return true;
        }

        /// <summary>
        ///Move 90 degrees to the right of position1.
        /// </summary>
        /// <param name="tmpPieces">The TMP pieces.</param>
        /// <returns></returns>
        private bool moveToPosition2(TetrominoBlock[] tmpPieces)
        {
            if (hasColisionInIncompleteBlock(tmpPieces[BLOCK_0].getX() + 1, tmpPieces[BLOCK_0].getY() + 1))
            {
                moveLeft(tmpPieces);
            }
            tmpPieces[BLOCK_0].addX(1);
            tmpPieces[BLOCK_0].addY(1);

            tmpPieces[BLOCK_2].addX(-1);
            tmpPieces[BLOCK_2].addY(-1);

            tmpPieces[BLOCK_3].addX(1);
            tmpPieces[BLOCK_3].addY(-1);
            return true;
        }

        /// <summary>
        /// Move 90 degrees to the right of position2.
        /// </summary>
        /// <param name="tmpPieces">The TMP pieces.</param>
        /// <returns></returns>
        private bool moveToPosition3(TetrominoBlock[] tmpPieces)
        {
            tmpPieces[BLOCK_0].addX(-1);
            tmpPieces[BLOCK_0].addY(1);

            tmpPieces[BLOCK_2].addX(1);
            tmpPieces[BLOCK_2].addY(-1);

            tmpPieces[BLOCK_3].addX(1);
            tmpPieces[BLOCK_3].addY(1);
            return true;
        }

        /// <summary>
        /// Rotates to right.
        /// </summary>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        private bool rotateToRight(int position)
        {
            TetrominoBlock[] pieceCopy = copyPiece(tetromino);

            clearCurrentTetromino();
            switch (position)
            {
                case 0: // L em pe
                    moveToPosition0(pieceCopy);
                    break;
                case 1: // L deitado
                    moveToPosition1(pieceCopy);
                    break;
                case 2: // L de cadeica pra baixo
                    if (!moveToPosition2(pieceCopy))
                    {
                        return false;
                    }
                    break;
                case 3: // L deitado pro outro lado
                    moveToPosition3(pieceCopy);
                    break;
                default:
                    return false;
            }
            return updateTetrominoPosition(pieceCopy);
        }

        /// <summary>
        /// Rotates the tetromino clockwisely.
        /// </summary>
        /// <returns></returns>
        public override bool rotate()
        {
            int oldPosition = currentPosition;
            currentPosition = (currentPosition + 1) % 4;
            bool rotateStatus = rotateToRight(currentPosition);
            if (!rotateStatus)
            {
                currentPosition = oldPosition;
            }
            fillCurrentTetromino(COLOR_IN_ACTION);
            return rotateStatus;
        }

        /// <summary>
        /// Returns the color of the tetromino.
        /// </summary>
        /// <returns></returns>
        public override int color()
        {
            return COLOR;
        }
        /// <summary>
        /// When a line is done by the player, it should be erased. Because of that, we decided
        /// to represent the piece that is falling down by a different state, which is represented
        /// by a color, so when we move down all the blocks above the line that was made, the
        /// tetromino that is falling should not move down.
        /// </summary>
        /// <returns></returns>
        protected override int colorWhileFalling()
        {
            return COLOR_IN_ACTION;
        }
    }
}